#include "common.hpp"

// 程序开始时调用Init构造函数创建管道文件
// 程序结束时调用析构函数销毁管道文件
Init init;

int main()
{
    // 1. 获取共享内存空间的key值
    key_t k = ftok(PATH_NAME, PROG_ID);
    if(k == -1)
    {
        log("Serve# ftok", ERROR) << std::endl;
        exit(1);
    }
    log("Serve# creat key done", DEBUG) << "key:" << TransToHex(k) << std::endl;

    // 2. 申请共享内存
    int shmid = shmget(k, SIZE, IPC_CREAT | IPC_EXCL | 0666);
    //int shmid = shmget(k, SIZE, 0);
    if(shmid == -1)
    {
        perror("Serve# shmget");
        exit(2);
    }
    log("Serve# creat shm done", DEBUG) << "shmid:" << shmid << std::endl; 
    //sleep(7);

    // 3.将共享内存与虚拟地址挂接
    char* shmaddr = (char*)shmat(shmid, NULL, 0);
    if(shmaddr == nullptr)
    {
        perror("Serve# shmat");
        exit(3);
    }
    log("Serve# attach shm done", DEBUG) << "shmid: " << shmid << std::endl;
    //sleep(7);

    // 进程间通信代码
    // 服务端读取数据，可以认为是从一个大型的字符串的获取数据
    int fd = OpenFifo(FIFO_NAME, READ);
    while(true)
    {
        WaitRead(fd);
        printf("Client message# %s\n", shmaddr);
        if(strcmp(shmaddr, "quit") == 0) break;
        // sleep(1);  // 间隔1s读取数据
    }

    // 4. 共享内存与虚拟地址（地址空间）解绑
    int n = shmdt(shmaddr);
    if(n == -1)
    {
        perror("shmdt");
        exit(4);
    }
    log("Serve# detach shm done", DEBUG) << "shmid: " << shmid << std::endl;
    //sleep(7);

    // 5. 删除共享内存
    // 即使有进程与当前的共享内存相关联，shmctl - IPC_RMID也可以删除共享内存
    n = shmctl(shmid, IPC_RMID, nullptr);
    if(n == -1)
    {
        perror("shmctl");
        exit(5);
    }
    log("Serve# shm delete done", DEBUG) << "shmid: " << shmid << std::endl;

    CloseFifo(fd);

    return 0;
}